package org.xxpay.manage.config.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.xxpay.core.common.annotation.MethodLog;
import org.xxpay.core.common.constant.Constant;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.domain.BizResponse;
import org.xxpay.core.common.domain.XxPayPageRes;
import org.xxpay.core.common.domain.XxPayResponse;
import org.xxpay.core.common.util.FileUtils;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.XXPayUtil;
import org.xxpay.core.common.vo.DBApplicationConfig;
import org.xxpay.core.entity.PayInterfaceType;
import org.xxpay.core.entity.PayInterfaceTypeTemplate;
import org.xxpay.core.entity.PayPassage;
import org.xxpay.core.entity.PayPassageAccount;
import org.xxpay.manage.common.config.MainConfig;
import org.xxpay.manage.common.ctrl.BaseController;
import org.xxpay.manage.common.service.RpcCommonService;
import org.xxpay.manage.config.service.CommonConfigService;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;

/**
 * @author: dingzhiwei
 * @date: 18/05/04
 * @description: 支付通道账户
 */
@RestController
@RequestMapping(Constant.MGR_CONTROLLER_ROOT_PATH + "/config/pay_passage_account")
public class PayPassageAccountController extends BaseController {

    private static final MyLog logger = MyLog.getLog(PayPassageAccountController.class);

    @Autowired
    private RpcCommonService rpcCommonService;

    @Autowired
    private CommonConfigService commonConfigService;

    @Autowired
    private MainConfig mainConfig;

    @RequestMapping("/list")
    @ResponseBody
    public ResponseEntity<?> list(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);
        int count = commonService.payPassageAccountService.count(payPassageAccount);
        if(count == 0) return ResponseEntity.ok(XxPayPageRes.buildSuccess());
        List<PayPassageAccount> list = commonService.payPassageAccountService.select((getPageIndex(param) - 1) * getPageSize(param), getPageSize(param), payPassageAccount);
        // 支付通道列表
        List<PayPassage> payPassageList = commonService.payPassageService.selectAll(new PayPassage());
        // 转换前端显示
        List<Map> objects = new LinkedList<>();
        Map<Integer, PayPassage> payPassageMap = new HashMap<>();
        for (PayPassage passage:payPassageList) {
            payPassageMap.put(passage.getId(), passage);
        }
        for (PayPassageAccount passageAccount: list) {
            JSONObject object = (JSONObject) JSON.toJSON(passageAccount);
            if (payPassageMap.get(passageAccount.getPayPassageId()) != null) {
                object.put("configType", payPassageMap.get(passageAccount.getPayPassageId()).getConfigType());
            }
            objects.add(object);
        }
        return ResponseEntity.ok(XxPayPageRes.buildSuccess(objects, count));
    }

    @RequestMapping("/get")
    @ResponseBody
    public ResponseEntity<?> get(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        Integer id = getIntegerRequired(param, "id");
        PayPassageAccount payPassageAccount = commonService.payPassageAccountService.findById(id);

        if(payPassageAccount != null && StringUtils.isNotEmpty(payPassageAccount.getParam())){

            JSONObject paramJSON = JSON.parseObject(payPassageAccount.getParam());
            this.processParamDesensitization(payPassageAccount.getIfTypeCode(), (key) -> paramJSON.put(key, XXPayUtil.autoDesensitization(paramJSON.getString(key))));
            payPassageAccount.setParam(paramJSON.toJSONString());
        }

        return ResponseEntity.ok(XxPayResponse.buildSuccess(payPassageAccount));
    }

    @RequestMapping("/update")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户" )
    public ResponseEntity<?> update(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);

        //查询当前支付通道账号信息
        PayPassageAccount dbPassageAccount = commonService.payPassageAccountService.findById(payPassageAccount.getId());
        PayInterfaceType payInterfaceType = commonService.payInterfaceTypeService.findByCode(dbPassageAccount.getIfTypeCode());
        if(payInterfaceType.getMustFromTemplate() == MchConstant.PUB_YES){ //强制使用模板
            PayInterfaceTypeTemplate template = commonService.payInterfaceTypeTemplateService.findById(payPassageAccount.getTemplateId());
            if(template == null) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_FOUND));
            if(template.getStatus() != MchConstant.PUB_YES) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_AVAILABLE));
            //将模板参数赋值到payPassageAccount对象中
            payPassageAccount.setParam(template.getParamTemplate());
            payPassageAccount.setPassageMchId(template.getPassageMchIdTemplate());
        }else{

            JSONObject updateParam = JSON.parseObject(payPassageAccount.getParam());
            JSONObject dbParam = JSON.parseObject(dbPassageAccount.getParam());

            this.processParamDesensitization(dbPassageAccount.getIfTypeCode(), (key) -> {
                if(StringUtils.isEmpty(updateParam.getString(key))){ //未更改
                    updateParam.put(key, dbParam.getString(key));
                }
            });
            payPassageAccount.setParam(updateParam.toJSONString());

            payPassageAccount.setTemplateId(0L);
        }

        //通道商户ID发生变化 : 判断通道商户是否存在，避免抛出数据库异常错误
        if(!dbPassageAccount.getPassageMchId().equals(payPassageAccount.getPassageMchId())){
            PayPassageAccount selectRecord = new PayPassageAccount();
            selectRecord.setPayPassageId(dbPassageAccount.getPayPassageId());
            selectRecord.setPassageMchId(payPassageAccount.getPassageMchId());
            if(commonService.payPassageAccountService.count(selectRecord) > 0){
                return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_SERVICE_PASSAGE_MCH_ID_EXISTS));
            }
        }


        //查询支付通道信息
        PayPassage payPassage = commonService.payPassageService.findById(dbPassageAccount.getPayPassageId());

        int count = commonService.payPassageAccountService.update(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }

    @RequestMapping("/updateRisk")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户风控规则" )
    public ResponseEntity<?> updateRisk(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        handleParamAmount(param, "maxDayAmount", "maxEveryAmount", "minEveryAmount");
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);

        //避免不必要的更新
        payPassageAccount.setAccountName(null);
        payPassageAccount.setPassageMchId(null);
        payPassageAccount.setParam(null);
        payPassageAccount.setTemplateId(null);

        int count = commonService.payPassageAccountService.update(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }


    @RequestMapping("/add")
    @ResponseBody
    @MethodLog( remark = "新增支付通道子账户" )
    public ResponseEntity<?> add(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        PayPassageAccount payPassageAccount = getObject(param, PayPassageAccount.class);

        Integer payPassageId = getIntegerRequired(param, "payPassageId");
        PayPassage payPassage = commonService.payPassageService.findById(payPassageId);
        if(payPassage == null) {
            return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_PAY_PASSAGE_NOT_EXIST));
        }

        PayInterfaceType payInterfaceType = commonService.payInterfaceTypeService.findByCode(payPassage.getIfTypeCode());
        if(payInterfaceType.getMustFromTemplate() == MchConstant.PUB_YES){ //强制使用模板
            PayInterfaceTypeTemplate template = commonService.payInterfaceTypeTemplateService.findById(payPassageAccount.getTemplateId());
            if(template == null) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_FOUND));
            if(template.getStatus() != MchConstant.PUB_YES) return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_MGR_TEMPLATE_NOT_AVAILABLE));
            //将模板参数赋值到payPassageAccount对象中
            payPassageAccount.setParam(template.getParamTemplate());
            payPassageAccount.setPassageMchId(template.getPassageMchIdTemplate());
        }else{
            payPassageAccount.setTemplateId(0L);
        }

        //判断通道商户是否存在，避免抛出数据库异常错误
        PayPassageAccount selectRecord = new PayPassageAccount();
        selectRecord.setPayPassageId(payPassageId);
        selectRecord.setPassageMchId(payPassageAccount.getPassageMchId());
        if(commonService.payPassageAccountService.count(selectRecord) > 0){
            return ResponseEntity.ok(XxPayResponse.build(RetEnum.RET_SERVICE_PASSAGE_MCH_ID_EXISTS));
        }

        payPassageAccount.setIfCode(payPassage.getIfCode());            // 设置支付接口代码
        payPassageAccount.setIfTypeCode(payPassage.getIfTypeCode());    // 设置接口类型代码

        payPassageAccount.setPassageRate(payPassage.getPassageRate());  // 设置通道费率
        int count = commonService.payPassageAccountService.add(payPassageAccount);
        if(count == 1) return ResponseEntity.ok(BizResponse.buildSuccess());
        return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
    }

    @RequestMapping("/updateState")
    @ResponseBody
    @MethodLog( remark = "修改支付通道子账户" )
    public ResponseEntity<?> updateAccountState(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        String IdsParam = getStringRequired(param, "ids");
        Byte state = getByte(param, "state");
        JSONArray ids = JSON.parseArray(IdsParam);
        int count = 0;
        if(ids.size() > 0 ){
            for(Object id: ids){
                PayPassageAccount passageAccount = new PayPassageAccount();
                if (state.equals(MchConstant.PUB_YES)){
                    passageAccount.setId(Integer.valueOf(id.toString()));
                    passageAccount.setStatus(MchConstant.PUB_NO);
                    commonService.payPassageAccountService.update(passageAccount);
                }else {
                    passageAccount.setId(Integer.valueOf(id.toString()));
                    passageAccount.setStatus(MchConstant.PUB_YES);
                    commonService.payPassageAccountService.update(passageAccount);
                }
                count ++;
            }

            if (count <= 0) return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));

            return ResponseEntity.ok(BizResponse.buildSuccess());
        }else {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_COMM_OPERATION_FAIL));
        }
    }

    @RequestMapping("/relationDelete")
    @ResponseBody
    @MethodLog( remark = "彻底删除支付通道子账户" )
    public ResponseEntity<?> delAccount(String ids, String superPassword) {
        checkSecurityReq(null);  //敏感操作，用户安全认证校验

        //验证删除开关是否打开
        DBApplicationConfig config = getDBApplicationConfig();
        if (config.getCleanFlag() != MchConstant.PUB_YES) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.RET_MGR_DATA_CLEAN_FLAG_OFF));
        }

        List<Integer> idsLong = JSON.parseArray(ids, Integer.class);
        int delNum = commonService.payPassageAccountService.deleteByIds(idsLong);
        return ResponseEntity.ok(XxPayResponse.buildSuccess(delNum));
    }

    /** 接口验证 **/
    @RequestMapping("/channelTest")
    @ResponseBody
    public ResponseEntity<?> channelTest(HttpServletRequest request) {
        JSONObject param = getJsonParam(request);
        Integer id = getIntegerRequired(param, "id");
        String result = rpcCommonService.rpcXxPayPassageTestService.test(id);
        return ResponseEntity.ok(BizResponse.build(result));
    }


    /** 上传附件  */
    @RequestMapping("/uploadParamFile")
    public XxPayResponse cert(@RequestParam("file") MultipartFile file) {

        if( file == null ) return XxPayResponse.build(RetEnum.RET_COMM_PARAM_ERROR);

        try {

            //1. 待保存文件的名称
            String saveFileName = UUID.randomUUID() + FileUtils.getFileSuffix(file.getOriginalFilename(), true);

            //2. 保存文件
            String savePath = mainConfig.getCertRootPath() + File.separator + saveFileName;
            saveFile(file, savePath);

            //3. 返回响应地址
            return XxPayResponse.buildSuccess(saveFileName);

        } catch (Exception e) {
            logger.error("upload error, fileName = {}", file == null ? null :file.getOriginalFilename(), e);
            return XxPayResponse.build(RetEnum.RET_COMM_OPERATION_FAIL);
        }
    }


    /** 处理加密参数 **/
    private void processParamDesensitization(String ifTypeCode, InnerInterface callbackFunc){

        PayInterfaceType payInterfaceType = commonService.payInterfaceTypeService.findByCode(ifTypeCode);
        if(payInterfaceType != null && StringUtils.isNotEmpty(payInterfaceType.getParam())){
            JSON.parseArray(payInterfaceType.getParam()).stream().forEach(t -> {
                JSONObject tJSON = (JSONObject) t;
                if("1".equals(tJSON.getString("star"))){
                    callbackFunc.process(tJSON.getString("name"));
                }
            });
        }
    }

    // 回调接口
    interface InnerInterface{
        /** 处理 需要加密的数据 **/
        void process(String key);
    }




}
